问题简单描述: 服务端负载均衡 4 层有超时配置,如果没有数据交互,那么 tcp 连接会断开。
为了支持可定制化配置,需要验证超时生效的问题,于是我做了一个简单的 Flask app 的镜像(启动在8083 端口, 120 秒返回结果),启动后,
使用 curl http://ip:8083 发现, 过了超时时间后,服务端仍然完整了返回了结果。
调查:这种问题,一般用 tcpdump 跟踪一下就容易解决。
1 | 08:19:59.630162 IP myhost.24435 > VIP.http: Flags [P.], seq 1:77, ack 1, win 58, length 76 |
可以看到在 60 秒,myhost 发送了一个类似心跳的消息,这就是为什么超时后,连接仍然没有端口的原因了。
这个问题显然是 curl 程序本身的设置,查 curl 文档 https://curl.haxx.se/docs/manpage.html 发现
1 | --keepalive-time |
原因找到了,我们再验证一下,是否是这个导致,验证如下:
- 设置一个小于 4层默认超时时间,但是大于 curl 本身的超时时间,这里设置 70s,
curl -v –keepalive-time 70 -X GET http://ip:8083
tcpdump 如下:
1 | 08:25:46.112532 IP myhost.31425 > VIP.http: Flags [.], ack 1, win 58, length 0 |
没有问题,70s 发送了心跳
- 设置一个大于 4 层超时时间的配置,但是小于服务端程序本身的响应时间,这里设置为 100 秒
curl -v –keepalive-time 100 -X GET http://ip:8083
tcpdump 如下:
1 | 08:48:44.235749 IP myhost.64757 > VIP.http: Flags [.], ack 1, win 58, length 0 |
收到了 Rest 包,没有问题
经过上面的分析,我们就明白了,验证问题本身,使用的测试程序不同,直接结果可能表现不一样,
这需要我们深入到测试程序本身,搞明白其中相关的设置,避免不必要的误解。
最后,上面如果用 telnet 测试,就不会衍生出上面的这个问题了,因为 telnet 默认没有相关的心跳维护,自然不会出现 curl 上面的问题了。